#ifndef __RS485_PRIVATE_DEVICE_H__
#define __RS485_PRIVATE_DEVICE_H__
#include "rs485_hardware_driver_common.h"
#include <stdint.h>
#define UART_RTX_BUFFER_SIZE 300
#define PR_EOK               0  /**< There is no error */
#define PR_ERROR             1  /**< A generic error happens */
#define PR_ETIMEOUT          2  /**< Timed out */
#define PR_EFULL             3  /**< The resource is full */
#define PR_EEMPTY            4  /**< The resource is empty */
#define PR_ENOMEM            5  /**< No memory */
#define PR_ENOSYS            6  /**< No system */
#define PR_EBUSY             7  /**< Busy */
#define PR_EIO               8  /**< IO error */
#define PR_EINTR             9  /**< Interrupted system call */
#define PR_EINVAL            10 /**< Invalid argument */

typedef enum {
  STANDBY = 0,
  RECEIVEING,
  SENDING,

} rs485_private_device_status_dpt;

struct rs485_rtx_st {
  uint8_t buffer[UART_RTX_BUFFER_SIZE];
  uint32_t read_index, save_index;
  uint8_t status;
};

struct rs485_private_device_st {
  /* rx structure */
  struct rs485_rtx_st *rx;
  struct rs485_rtx_st *rx_finished;
  /* tx structure */
  struct rs485_rtx_st *tx;
  // struct rt_semaphore* sem_rx_finish;
  uint8_t running_status;
  struct rs485_hw *hw_st;
  void (*watchdog_feed)(void);
  void (*microsecond_delay)(unsigned int microseconds);
  int (*wait_send_data_finished)(
      struct rs485_private_device_st *rs485_p_device);
  void (*enable_uart)(struct rs485_private_device_st *);
  void (*start_to_send_out)(struct rs485_private_device_st *rs485_p_device,
                            uint8_t *buf, uint16_t size);
  uint8_t (*check_receive_interrupt)(
      struct rs485_private_device_st *rs485_p_device, uint8_t *buf);
  void (*add_one_byte_to_received_buffer)(
      struct rs485_private_device_st *rs485_p, uint8_t byte);
  void (*send_out_frame_process)(struct rs485_private_device_st *rs485_p);
  uint8_t (*fetch_one_need_send_byte)(struct rs485_private_device_st *rs485_p,
                                      uint8_t *byte);
  uint8_t (*check_receive_timeout_timer_interrupt)(
      struct rs485_private_device_st *rs485_p);
  void (*receive_timeout_proccess)(struct rs485_private_device_st *rs485_p);
};
int rs485_private_device_st_register(
    struct rs485_private_device_st *rs485_p_device, struct rs485_rtx_st *rx_st,
    struct rs485_rtx_st *rx_f_st, struct rs485_rtx_st *tx,
    struct rs485_hw *hw_st, void (*seconds_delay)(unsigned int seconds),
    void (*watchdog_feed)(void));
/**
 * @brief
 *
 * @param rs485_p_device
 * @param pos
 * @param send_buffer
 * @param size
 * @param response_buffer
 * @param response_szie
 * @param response_timeout unit: ms
 * @return int 0 : success, other : failed
 */
int rs485_private_send_out_order_and_fetch_response(
    struct rs485_private_device_st *rs485_p_device, uint16_t pos,
    uint8_t *send_buffer, uint16_t size, uint8_t *response_buffer,
    uint16_t *response_szie, uint16_t response_timeout);
uint16_t rs485_private_write(struct rs485_private_device_st *rs485_p_device,
                             uint16_t pos, const void *buffer, uint16_t size);
uint16_t rs485_private_read(struct rs485_private_device_st *rs485_p_device,
                            uint16_t pos, void *buffer, uint16_t size);

void rs485_private_rtx_isr(struct rs485_private_device_st *rs485_p_device);
void rs485_private_rx_tim_isr(struct rs485_private_device_st *rs485_p_device);

int wait_send_data_finished(struct rs485_private_device_st *rs485_p_device);

static void enable_st_uart(struct rs485_private_device_st *rs485_p_device);
static void start_to_send_out(struct rs485_private_device_st *rs485_p_device,
                              uint8_t *buf, uint16_t size);

uint8_t check_receive_interrupt(struct rs485_private_device_st *rs485_p_device,
                                uint8_t *buf);
void add_one_byte_to_received_buffer(struct rs485_private_device_st *rs485_p,
                                     uint8_t byte);
void send_out_frame_process(struct rs485_private_device_st *rs485_p);
uint8_t fetch_one_need_send_byte(struct rs485_private_device_st *rs485_p,
                                 uint8_t *byte);
uint8_t
check_receive_timeout_timer_interrupt(struct rs485_private_device_st *rs485_p);
void receive_timeout_proccess(struct rs485_private_device_st *rs485_p);

#endif
